在現代的 IT 基礎架構中,將一台 Linux 伺服器暴露在網際網路,或是將一台主機放置在物理可接觸的環境中,無異於將其置身於充滿惡意掃描、自動化漏洞利用與實體攻擊的戰場。
單一的安全機制(例如只裝防火牆)早已無法應付複雜的威脅。本篇技術分享將帶領大家探討「深度防禦」在 Ubuntu 系統上的具體實作。我們不僅會提供一套自動化的加固腳本,更會深入作業系統底層,解析這些防禦機制是如何運作的。
核心架構理念:深度防禦的八大防線
這套防禦架構的設計思維建立在「假設攻擊者必然會突破某一道防線」的前提下。因此,我們需要在攻擊鏈的每一個節點設置絆馬索:
網路邊界:UFW 最小化暴露面,結合 Fail2Ban 阻擋自動化暴力破解。
通道防護:SSH 四層深度加固與 ForceCommand 指令白/黑名單過濾,搭配 PAM 登入攔截。
實體存取:監控實體裝置接入並從驅動層阻擋。
檔案系統:防範核心設定檔被惡意竄改。
行程執行:揪出潛伏的惡意執行檔與挖礦程式。
系統服務:防止防護機制自身被惡意終止。
惡意掃描:定期執行數位指紋與 Rootkit 基準線比對。
稽核軌跡:確保駭客無法抹除犯罪證據。
以下我們將逐一拆解這些防護模組的底層原理。
模組原理解析
1. 核心金庫與通訊解耦
面臨威脅:寫死在程式碼中的 API Token 極易因為權限設定不當而遭竊。
底層實作:
在 Linux 系統中,檔案建立的瞬間到權限被修改的空窗期,可能存在「瞬讀風險」。我們放棄了常見的
touch+chmod做法,改用install -m 600。這能確保檔案在虛擬檔案系統註冊的瞬間,就已經具備絕對嚴格的權限。此外,在與 Telegram API 通訊時,若遭遇 DNS 解析失敗或網路延遲,會導致呼叫端被卡死。因此我們的共用發送腳本強制實作了
--connect-timeout與--max-time的非阻塞設計。
2. SSH 深度加固與指令防護
面臨威脅:密碼外洩、私鑰被盜用、以及利用自動化腳本進行破壞性的遠端指令注入。
底層實作:
四層加固機制:我們透過 Drop-in 配置,強制廢除密碼登入、強制僅限金鑰登入、並進一步限縮至現代的高強度演算法。最後,透過
AllowUsers與動態注入from="CIDR"參數到authorized_keys,將連線來源鎖死在特定網段。指令攔截器:當外部傳入指令時,我們利用
ForceCommand將指令攔截至$SSH_ORIGINAL_COMMAND變數中,並透過正規表示式進行黑名單比對。工程細節:為了避免破壞 SCP/SFTP 等依賴乾淨標準輸出的二進位通訊協定,攔截器中特別加入了子系統放行邏輯,並確保一般指令透過
/bin/sh -c執行,而非會載入 Profile 的/bin/bash -l,徹底解決了常見的協定相容性痛點。
3. 防鎖死設計與網路邊界
面臨威脅:自動化腳本執行防火牆設定時,常因為規則套用順序錯誤,導致維運人員自己被踢出 SSH 連線(俗稱「拔自己網線」)。
底層實作:
在啟用 UFW 防火牆時,腳本實作了「狀態感知」機制。它會透過檢查
$SSH_CONNECTION判斷當前是否處於遠端 SSH 工作階段;如果是,且 UFW 尚未啟用,腳本會將模式切換為safe。此時只會將白名單規則寫入核心,但不主動觸發ufw enable,將最終的啟動權交還給維運人員,確保連線絕對安全。
4. 帳號與關鍵檔案監控
面臨威脅:攻擊者提權後建立後門帳號或修改 Sudo 權限。
底層實作:
這依賴了 Linux 核心的
inotify子系統。當我們要求監控/etc/passwd時,核心會在記憶體的 Inode 結構上掛載一個 Hook。工程細節:為什麼我們要同時監聽
close_write,move,create,delete?因為很多編輯器為了確保寫入安全,採用的是「原子替換」。它們會先寫入一個暫存檔,再使用mv覆蓋原檔案。如果只監聽modify,我們將完全漏報這類竄改行為。
5. USB 實體層防護與熱插拔中斷
面臨威脅:BadUSB 鍵盤注入攻擊、惡意儲存裝置掛載。
底層實作:
利用 Linux 核心裝置管理員
udev監聽來自核心的硬體插拔事件。工程細節:在 udev 的
RUN+=指令中執行的腳本有嚴格的執行時間限制,且會阻擋裝置初始化的流程。因此我們使用/usr/bin/systemd-run --no-block --collect,將通知任務委託給 Systemd 建立一個拋棄式的背景服務來執行,--collect參數則確保任務結束後立即釋放記憶體,避免系統遺留垃圾服務。同時配合 USBGuard 從驅動層直接阻擋資料傳輸。
6. 系統狀態守護者
面臨威脅:攻擊者取得 Root 權限後,第一時間嘗試終止我們的防護服務。
底層實作:
我們利用 Systemd 的 Drop-in 機制為現有服務無損注入邏輯。
工程細節:我們刻意不使用
ExecStopPost=,因為這會覆蓋某些服務原有的停止清理邏輯,造成不可預期的結果。我們採用了更優雅的OnFailure=service-protector-alert@%n樣板設計。這意味著只有當服務發生「異常崩潰」或「被強制終止」時才會觸發,這是在日常維運與資安監控之間的合理平衡。
7. 行程白名單與 Procfs 差異比對
面臨威脅:未知惡意程式在記憶體中偷偷運行。
底層實作:
這是一套基於虛擬檔案系統的輪詢稽核機制。腳本透過
ps -e -o exe=直接讀取每一個執行中行程的可執行檔來源。透過標準的 Linux 文字處理工具comm -23,快速求出「當前執行快照」與「系統基準線白名單」的差集,揪出不速之客,並實作了基於雜湊的狀態機,實現了優雅的連續警報與自動靜音機制。
8. 核心底層稽核
面臨威脅:攻擊者入侵後執行
history -c或echo "" > /var/log/auth.log銷毀證據。底層實作:
Auditd:運作於核心空間。它可以攔截系統呼叫,在應用程式實際讀寫檔案或執行指令「之前」,就透過 Netlink Socket 將操作記錄寫入
/var/log/audit/audit.log。我們特別加入了針對execve的系統呼叫追蹤,即使是透過 SSH 進入後產生的任何子行程,都會被完整記錄。Journald:為了防範日誌洪泛攻擊導致硬碟被塞爆,我們強制將 Systemd 的日誌持久化至硬碟,並硬性規範
SystemMaxUse=1G。
實戰:系統加固一鍵部署腳本
在理解了底層原理後,我們將上述所有的防禦機制整合成了一份具備「高容錯、防鎖死、冪等性」的 Bash 部署腳本。
安裝步驟:
取得你的 Telegram Bot Token 與 Chat ID。
建立腳本
nano ubuntu_ultimate_security_setup.sh並貼入下方原始碼。修改最上方的「全域設定區」。
賦予權限並執行:
chmod +x ubuntu_ultimate_security_setup.sh && sudo ./ubuntu_ultimate_security_setup.sh
#!/bin/bash
set -euo pipefail
# ==============================================================================
# Ubuntu 終極全方位安全監控系統 - 企業加固版一鍵安裝腳本
# 具備:
# - Telegram 通知(Token 隔離、非阻塞)
# - SSH 登入即時通知(PAM)
# - SSH 指令阻擋(ForceCommand + Regex 黑名單,含 scp/sftp/rsync 放行)
# - SSH 四層強化:禁密碼 / 強制 Key(Ed25519) / AllowUsers / authorized_keys from= 限來源
# - UFW(最小暴露面:只放行指定來源到 SSH;預設允許 outgoing → 不影響上網)
# - Fail2Ban(含 TG 封鎖通知)
# - USBGuard + 熱插拔通知
# - 帳號與關鍵檔案監控(inotify)
# - 程序白名單監控
# - 服務崩潰(OnFailure) 與服務檔案守護(inotify)
# - Journald 強化 + Auditd 基礎規則
# - RKHunter 掃描(可設定時間;systemd timer)
#
# 防鎖死保護:
# - SSH_HARDEN_MODE="safe":若 AllowUsers 中有人未放 authorized_keys,暫不關閉密碼登入/不強制 publickey-only
# - 保留救援群組 SSH_RESCUE_GROUP(ForceCommand 不套用於該群組)
# - UFW_ENABLE="safe":若偵測在 SSH 遠端執行且 UFW 尚未啟用,僅寫規則不自動 enable(避免鎖死)
# ==============================================================================
# ==============================================================================
# 【全部可調設定區】(你要求:所有要設定的項目放腳本開頭)
# ==============================================================================
# --- Telegram 通知 ---
MY_TOKEN="xxx"
MY_CHAT_ID="xxx"
# --- 需要守護的 systemd 服務(空白分隔)---
PROTECT_SERVICES="ssh fail2ban usbguard process-monitor tg-account-monitor"
# ------------------------------------------------------------------------------
# SSH 四層強化(Hardening)設定
# ------------------------------------------------------------------------------
SSH_HARDEN_MODE="safe" # safe / always / never(safe 會避免鎖死)
SSH_PORT="22"
# 第一層:禁用密碼登入(若 safe 且未偵測到 authorized_keys 會暫不套用)
SSH_DISABLE_PASSWORD="true" # true/false
# 第二層:強制使用 SSH Key(publickey-only)
SSH_ENFORCE_PUBKEY_ONLY="true" # true/false
# 第二層補強:只接受 Ed25519 使用者公鑰(不想限制就 false)
SSH_REQUIRE_ED25519="true" # true/false -> PubkeyAcceptedAlgorithms ssh-ed25519
# 第三層:允許登入的使用者(空白分隔;留空表示不限制)
SSH_ALLOW_USERS="leoshiang"
# 第四層:在 authorized_keys 自動加上 from="CIDR"(留空表示不修改)
SSH_KEY_FROM_CIDR="192.168.1.0/24"
# 其他 SSH 建議參數
SSH_PERMIT_ROOT_LOGIN="no" # no / prohibit-password / yes(建議 no)
SSH_MAX_AUTH_TRIES="3"
SSH_LOGIN_GRACE_TIME="20"
SSH_CLIENT_ALIVE_INTERVAL="300"
SSH_CLIENT_ALIVE_COUNT_MAX="2"
SSH_DISABLE_FORWARDING="true" # true/false
# --- 救援機制(強烈建議保留)---
SSH_RESCUE_GROUP="ssh-rescue" # 此群組不套用 ForceCommand(避免腳本異常鎖死)
SSH_RESCUE_ALLOW_PASSWORD="true" # true/false(救援群組可保留密碼登入,避免鎖死)
# ------------------------------------------------------------------------------
# SSH 指令防護(ForceCommand)黑名單 Regex(ERE),一行一條規則
# 命中就阻擋;已支援「絕對路徑」繞過:(/path/)?cmd
# ------------------------------------------------------------------------------
SSH_BLOCK_REGEX_LIST=$'(^|[[:space:]])(/[^[:space:]]*/)?(shutdown|reboot|poweroff)([[:space:]]|$)\n'\
$'(^|[[:space:]])(/[^[:space:]]*/)?(useradd|adduser|usermod|userdel|passwd)([[:space:]]|$)\n'\
$'(^|[[:space:]])(/[^[:space:]]*/)?(visudo|sudo)([[:space:]]|$)\n'\
$'(^|[[:space:]])(/[^[:space:]]*/)?(rm|truncate)([[:space:]]+)(-rf[[:space:]]+)?(/var/log|/var/log/|/var/log/.*)([[:space:]]|$)\n'\
$'(^|[[:space:]])(/[^[:space:]]*/)?(systemctl)([[:space:]]+)(stop|disable|mask)([[:space:]]|$)\n'\
$'(^|[[:space:]])(/[^[:space:]]*/)?(sed|perl)([[:space:]]|$).*sshd?_config'
# 更嚴格(可選,取消註解)
# SSH_BLOCK_REGEX_LIST+=$'\n(^|[[:space:]])(/[^[:space:]]*/)?(curl|wget)([[:space:]]|$)'
# SSH_BLOCK_REGEX_LIST+=$'\n(^|[[:space:]])(/[^[:space:]]*/)?(chmod|chown)([[:space:]]|$)'
# ------------------------------------------------------------------------------
# UFW 防火牆(只放行來源網段到 SSH)
# ------------------------------------------------------------------------------
UFW_ENABLE="safe" # safe / always / never
UFW_ALLOW_SOURCES="192.168.1.0/24"
UFW_SSH_PORT="22"
# ------------------------------------------------------------------------------
# RKHunter 排程掃描(systemd timer)
# ------------------------------------------------------------------------------
ENABLE_RKHUNTER_SCHEDULE="true" # true/false
RKHUNTER_RUN_HOUR="22" # 0-23
RKHUNTER_RUN_MIN="30" # 0-59
# ==============================================================================
# 【以下為腳本主體】一般不需要改
# ==============================================================================
tg_safe_send() {
if [ -x /usr/local/bin/tg_send.sh ]; then
/usr/local/bin/tg_send.sh "$1" >/dev/null 2>&1 || true
fi
}
is_ssh_session() {
[ -n "${SSH_CONNECTION:-}" ]
}
ensure_sshd_include_dropin() {
if ! sudo grep -Eq '^\s*Include\s+/etc/ssh/sshd_config\.d/\*\.conf' /etc/ssh/sshd_config; then
echo "Include /etc/ssh/sshd_config.d/*.conf" | sudo tee -a /etc/ssh/sshd_config >/dev/null
fi
sudo mkdir -p /etc/ssh/sshd_config.d
}
authorized_keys_ready_for_user() {
local u="$1"
local home
home="$(getent passwd "$u" | cut -d: -f6 || true)"
[ -n "$home" ] && sudo test -s "$home/.ssh/authorized_keys"
}
ufw_is_active() {
sudo ufw status 2>/dev/null | grep -q "Status: active"
}
# ------------------------------------------
# 前置檢查
# ------------------------------------------
if [ -z "${MY_TOKEN:-}" ] || [ "${MY_TOKEN}" = "填入你的機器人Token" ]; then
echo "[錯誤] 請先在腳本頂端填入您的 Bot Token!"
exit 1
fi
if [ -z "${MY_CHAT_ID:-}" ] || [ "${MY_CHAT_ID}" = "填入你的數字ID" ]; then
echo "[錯誤] 請先在腳本頂端填入您的 Chat ID!"
exit 1
fi
echo "開始安裝「Ubuntu 終極全方位安全監控系統(企業加固版)」..."
export DEBIAN_FRONTEND=noninteractive
# 套件安裝
sudo apt-get update
sudo apt-get install -y \
inotify-tools curl mailutils rkhunter fail2ban usbguard auditd \
ufw openssh-server systemd-timesyncd
# ==============================================================================
# 模組 0: 核心憑證安全中心與共用發送器 (Secure Vault)
# ==============================================================================
echo "[0/10] 建立核心憑證金庫與 Telegram 發送器..."
sudo install -o root -g root -m 600 /dev/null /etc/secure-monitoring.env
sudo tee /etc/secure-monitoring.env >/dev/null <<EOF
TG_TOKEN="${MY_TOKEN}"
TG_CHAT_ID="${MY_CHAT_ID}"
EOF
sudo tee /usr/local/bin/tg_send.sh >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
[ -r /etc/secure-monitoring.env ] || { echo "secure-monitoring.env missing" >&2; exit 1; }
# shellcheck disable=SC1091
source /etc/secure-monitoring.env
: "${TG_TOKEN:?TG_TOKEN missing}"
: "${TG_CHAT_ID:?TG_CHAT_ID missing}"
msg="$(printf '%b' "${1:-}")"
curl -sS --fail-with-body --connect-timeout 3 --max-time 6 --retry 2 --retry-delay 1 --retry-all-errors \
-X POST "[https://api.telegram.org/bot$](https://api.telegram.org/bot$){TG_TOKEN}/sendMessage" \
--data-urlencode "chat_id=${TG_CHAT_ID}" \
--data-urlencode "text=${msg}" >/dev/null
EOF
sudo chmod 700 /usr/local/bin/tg_send.sh
sudo chown root:root /usr/local/bin/tg_send.sh
# ==============================================================================
# 模組 1: 帳號與關鍵檔案監控 (Account & File Monitor)
# ==============================================================================
echo "[1/10] 建立帳號與關鍵檔案監控..."
sudo tee /usr/local/bin/tg_account_monitor.sh >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
TARGETS="/etc/passwd /etc/shadow /etc/sudoers /etc/sudoers.d /usr/local/bin/tg_account_monitor.sh"
VALID_TARGETS=""
for t in $TARGETS; do
[ -e "$t" ] && VALID_TARGETS="$VALID_TARGETS $t"
done
if [ -z "$VALID_TARGETS" ]; then
/usr/local/bin/tg_send.sh "⚠️ tg-account-monitor 無有效監控目標,將於 30 秒後重試..." || true
sleep 30
exit 0
fi
FILES=""; DIRS=""
for t in $VALID_TARGETS; do
if [ -d "$t" ]; then
DIRS="$DIRS $t"
else
FILES="$FILES $t"
fi
done
send_alert() {
while IFS='|' read -r path action file; do
MSG="【關鍵檔案變更警報】\n路徑:${path}${file}\n動作:${action}\n時間:$(date '+%Y-%m-%d %H:%M:%S')\n主機:$(hostname)"
/usr/local/bin/tg_send.sh "$MSG" || true
done
}
pids=()
if [ -n "$FILES" ]; then
inotifywait -m --format '%w|%e|%f' -e close_write,attrib,move,create,delete $FILES | send_alert &
pids+=("$!")
fi
if [ -n "$DIRS" ]; then
inotifywait -m -r --format '%w|%e|%f' -e close_write,attrib,move,create,delete $DIRS | send_alert &
pids+=("$!")
fi
cleanup() { kill "${pids[@]:-}" 2>/dev/null || true; }
trap cleanup EXIT INT TERM
wait -n
exit 1
EOF
sudo chmod 700 /usr/local/bin/tg_account_monitor.sh
sudo chown root:root /usr/local/bin/tg_account_monitor.sh
sudo tee /etc/systemd/system/tg-account-monitor.service >/dev/null <<'EOF'
[Unit]
Description=Telegram Account and File Monitor
After=network.target
[Service]
Type=simple
ExecStart=/bin/bash /usr/local/bin/tg_account_monitor.sh
Restart=always
RestartSec=30
User=root
[Install]
WantedBy=multi-user.target
EOF
# ==============================================================================
# 模組 2: 系統 SSH 登入即時通知 (PAM Login Notification)
# ==============================================================================
echo "[2/10] 建立 SSH 遠端登入即時通知..."
sudo tee /usr/local/bin/login_notification.sh >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
if [ "${PAM_TYPE:-}" = "open_session" ]; then
MSG="【遠端登入警報】\n使用者:${PAM_USER}\n遠端主機:${PAM_RHOST:-本地端}\n終端:${PAM_TTY}\n時間:$(date '+%Y-%m-%d %H:%M:%S')\n主機:$(hostname)"
/usr/local/bin/tg_send.sh "$MSG" >/dev/null 2>&1 &
fi
exit 0
EOF
sudo chmod 700 /usr/local/bin/login_notification.sh
sudo chown root:root /usr/local/bin/login_notification.sh
if ! grep -q "login_notification.sh" /etc/pam.d/sshd; then
echo "session optional pam_exec.so /usr/local/bin/login_notification.sh" | sudo tee -a /etc/pam.d/sshd >/dev/null
fi
# ==============================================================================
# 模組 2.5: SSH 指令防護(ForceCommand 過濾/阻擋)
# ==============================================================================
echo "[2.5/10] 加上 SSH 指令防護(過濾/阻擋特定指令)..."
sudo install -o root -g root -m 600 /dev/null /etc/ssh/ssh_command_blocklist.regex
printf "%s\n" "${SSH_BLOCK_REGEX_LIST}" | sudo tee /etc/ssh/ssh_command_blocklist.regex >/dev/null
sudo tee /usr/local/bin/ssh_command_guard.sh >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
BLOCKLIST="/etc/ssh/ssh_command_blocklist.regex"
ORIG="${SSH_ORIGINAL_COMMAND:-}"
USER="${USER:-${LOGNAME:-unknown}}"
log() { logger -p authpriv.notice -t ssh-cmd-guard -- "$1"; }
tg() {
if [ -x /usr/local/bin/tg_send.sh ]; then
/usr/local/bin/tg_send.sh "$1" >/dev/null 2>&1 || true
fi
}
# 互動 shell(沒有命令)放行
if [ -z "$ORIG" ]; then
exec /bin/bash -l
fi
# 黑名單匹配(ERE)
if [ -r "$BLOCKLIST" ]; then
while IFS= read -r rule; do
[ -z "$rule" ] && continue
if echo "$ORIG" | grep -Eiq -- "$rule"; then
SRC="${SSH_CONNECTION:-unknown}"
MSG="【SSH 指令阻擋】\n使用者:${USER}\n來源:${SRC}\n命令:${ORIG}\n時間:$(date '+%Y-%m-%d %H:%M:%S')\n主機:$(hostname)"
log "BLOCK user=$USER src=$SRC cmd=$ORIG"
tg "$MSG"
echo "Permission denied: command blocked by policy." >&2
exit 126
fi
done < "$BLOCKLIST"
fi
# --- 放行常見檔案傳輸/子系統,避免協定被 shell 輸出破壞 ---
case "$ORIG" in
internal-sftp*|sftp*|*sftp-server*)
if [ -x /usr/lib/openssh/sftp-server ]; then
exec /usr/lib/openssh/sftp-server
fi
exec /bin/sh -c "$ORIG"
;;
scp\ -*|scp\ *)
exec /bin/sh -c "$ORIG"
;;
rsync\ --server*)
exec /bin/sh -c "$ORIG"
;;
esac
log "ALLOW user=$USER cmd=$ORIG"
exec /bin/sh -c "$ORIG"
EOF
sudo chmod 700 /usr/local/bin/ssh_command_guard.sh
sudo chown root:root /usr/local/bin/ssh_command_guard.sh
ensure_sshd_include_dropin
sudo groupadd -f "${SSH_RESCUE_GROUP}"
# ForceCommand:預設套用所有帳號,但排除救援群組避免鎖死
sudo tee /etc/ssh/sshd_config.d/99-command-guard.conf >/dev/null <<EOF
PermitUserEnvironment no
Match Group !${SSH_RESCUE_GROUP}
ForceCommand /usr/local/bin/ssh_command_guard.sh
Match all
EOF
# ==============================================================================
# 模組 2.6: SSH 四層強化(禁密碼/Key-only/AllowUsers/from=)
# ==============================================================================
echo "[2.6/10] 套用 SSH 四層強化..."
# 1) 準備 host ed25519 key(若缺)
if [ ! -f /etc/ssh/ssh_host_ed25519_key ]; then
sudo ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N "" >/dev/null
fi
# 2) safe 模式:檢查 AllowUsers 中的 authorized_keys 是否就緒
keys_ready="true"
if [ -n "${SSH_ALLOW_USERS// }" ]; then
for u in ${SSH_ALLOW_USERS}; do
if ! authorized_keys_ready_for_user "$u"; then
keys_ready="false"
break
fi
done
fi
apply_strict="true"
if [ "${SSH_HARDEN_MODE}" = "never" ]; then
apply_strict="false"
elif [ "${SSH_HARDEN_MODE}" = "safe" ] && [ "${keys_ready}" != "true" ]; then
apply_strict="false"
tg_safe_send "⚠️【SSH safe 模式】AllowUsers 中有人尚未放置 ~/.ssh/authorized_keys(或為空),為避免鎖死:暫不關閉密碼登入/不強制 publickey-only。請先放公鑰後再改 SSH_HARDEN_MODE=always。"
fi
# 3) 寫入 SSH 加固設定(drop-in)
sudo tee /etc/ssh/sshd_config.d/10-hardening.conf >/dev/null <<EOF
# --- Hardening ---
Port ${SSH_PORT}
Protocol 2
HostKey /etc/ssh/ssh_host_ed25519_key
PermitRootLogin ${SSH_PERMIT_ROOT_LOGIN}
MaxAuthTries ${SSH_MAX_AUTH_TRIES}
LoginGraceTime ${SSH_LOGIN_GRACE_TIME}
ClientAliveInterval ${SSH_CLIENT_ALIVE_INTERVAL}
ClientAliveCountMax ${SSH_CLIENT_ALIVE_COUNT_MAX}
PubkeyAuthentication yes
PermitUserEnvironment no
EOF
if [ "${apply_strict}" = "true" ]; then
if [ "${SSH_DISABLE_PASSWORD}" = "true" ]; then
cat <<'EOF' | sudo tee -a /etc/ssh/sshd_config.d/10-hardening.conf >/dev/null
PasswordAuthentication no
KbdInteractiveAuthentication no
ChallengeResponseAuthentication no
EOF
fi
if [ "${SSH_ENFORCE_PUBKEY_ONLY}" = "true" ]; then
cat <<'EOF' | sudo tee -a /etc/ssh/sshd_config.d/10-hardening.conf >/dev/null
AuthenticationMethods publickey
EOF
fi
if [ "${SSH_REQUIRE_ED25519}" = "true" ]; then
cat <<'EOF' | sudo tee -a /etc/ssh/sshd_config.d/10-hardening.conf >/dev/null
PubkeyAcceptedAlgorithms ssh-ed25519
EOF
fi
else
cat <<'EOF' | sudo tee -a /etc/ssh/sshd_config.d/10-hardening.conf >/dev/null
# safe 模式:暫不強制禁用密碼/強制 publickey-only
EOF
fi
if [ "${SSH_DISABLE_FORWARDING}" = "true" ]; then
cat <<'EOF' | sudo tee -a /etc/ssh/sshd_config.d/10-hardening.conf >/dev/null
DisableForwarding yes
AllowAgentForwarding no
AllowTcpForwarding no
X11Forwarding no
PermitTunnel no
EOF
fi
# 第三層:AllowUsers
if [ -n "${SSH_ALLOW_USERS// }" ]; then
echo "AllowUsers ${SSH_ALLOW_USERS}" | sudo tee /etc/ssh/sshd_config.d/20-allowusers.conf >/dev/null
else
sudo rm -f /etc/ssh/sshd_config.d/20-allowusers.conf
fi
# 第四層:authorized_keys from="CIDR"(只對未含 from= 的 key 行補上)
if [ -n "${SSH_KEY_FROM_CIDR// }" ] && [ -n "${SSH_ALLOW_USERS// }" ]; then
for u in ${SSH_ALLOW_USERS}; do
home="$(getent passwd "$u" | cut -d: -f6 || true)"
[ -z "$home" ] && continue
sudo -u "$u" mkdir -p "$home/.ssh"
ak="$home/.ssh/authorized_keys"
if sudo test -s "$ak"; then
tmp="$(mktemp -p /run ak.${u}.XXXXXX)"
sudo cat "$ak" | while IFS= read -r line || [ -n "$line" ]; do
if [[ "$line" =~ ^[[:space:]]*# ]] || [ -z "${line// }" ]; then
echo "$line" >> "$tmp"
continue
fi
if echo "$line" | grep -Eq '(^|,|[[:space:]])from="'; then
echo "$line" >> "$tmp"
else
echo "from=\"${SSH_KEY_FROM_CIDR}\",$line" >> "$tmp"
fi
done
sudo install -o "$u" -g "$u" -m 600 "$tmp" "$ak"
rm -f "$tmp"
else
tg_safe_send "⚠️【SSH from= 未套用】使用者 ${u} 尚無 ${ak}(或為空)。請先放入公鑰後再重跑或手動在每行 key 前加:from=\"${SSH_KEY_FROM_CIDR}\","
fi
done
fi
# 救援群組是否允許密碼登入(可選)
if [ "${SSH_RESCUE_ALLOW_PASSWORD}" = "true" ]; then
sudo tee /etc/ssh/sshd_config.d/90-rescue.conf >/dev/null <<EOF
Match Group ${SSH_RESCUE_GROUP}
PasswordAuthentication yes
KbdInteractiveAuthentication yes
ChallengeResponseAuthentication no
PubkeyAuthentication yes
Match all
EOF
else
sudo rm -f /etc/ssh/sshd_config.d/90-rescue.conf
fi
# 重新載入 ssh
if sudo sshd -t; then
if systemctl is-active --quiet ssh; then
sudo systemctl reload ssh
else
sudo systemctl restart ssh || true
fi
fi
# ==============================================================================
# 模組 2.7: UFW 防火牆(最小暴露面)
# ==============================================================================
echo "[2.7/10] 設定 UFW 防火牆..."
if [ "${UFW_ENABLE}" != "never" ]; then
if [ "${UFW_ENABLE}" = "always" ]; then
sudo ufw --force reset >/dev/null 2>&1 || true
fi
# 不論是否 active,都確保預設策略
sudo ufw default deny incoming
sudo ufw default allow outgoing
# 放行 loopback
sudo ufw allow in on lo >/dev/null 2>&1 || true
sudo ufw allow out on lo >/dev/null 2>&1 || true
# 放行 SSH(限制來源網段)
if [ -n "${UFW_ALLOW_SOURCES// }" ]; then
sudo ufw allow from "${UFW_ALLOW_SOURCES}" to any port "${UFW_SSH_PORT}" proto tcp
else
sudo ufw allow "${UFW_SSH_PORT}/tcp"
fi
# safe:若遠端 SSH 執行且 UFW 尚未 active,避免鎖死 -> 不自動 enable
if [ "${UFW_ENABLE}" = "safe" ] && is_ssh_session && ! ufw_is_active; then
tg_safe_send "⚠️【UFW safe】偵測到 SSH 遠端執行,已寫入 UFW 規則但未自動啟用。\n請確認可從 ${UFW_ALLOW_SOURCES} 連線後再手動:sudo ufw enable"
echo "⚠️ UFW safe:規則已寫入但未自動 enable(避免鎖死)。"
else
sudo ufw --force enable >/dev/null 2>&1 || true
fi
fi
# ==============================================================================
# 模組 3: RKHunter 排程掃描與回報(可設定時間)
# ==============================================================================
echo "[3/10] 設定 RKHunter 掃描與排程..."
sudo rkhunter --update >/dev/null 2>&1 || true
sudo rkhunter --propupd >/dev/null 2>&1 || true
sudo tee /usr/local/bin/rkhunter_scan_tg.sh >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
TMP_FILE="$(mktemp -p /run rkhunter_warn.XXXXXX)"
sudo rkhunter --cronjob --report-warnings-only >"$TMP_FILE" 2>&1 || true
if [ -s "$TMP_FILE" ]; then
WARNINGS="$(head -n 30 "$TMP_FILE")"
MSG="【RKHunter 掃描警報】\n主機:$(hostname)\n時間:$(date '+%Y-%m-%d %H:%M:%S')\n\n偵測到異常:\n${WARNINGS}"
/usr/local/bin/tg_send.sh "$MSG" || true
fi
rm -f "$TMP_FILE"
EOF
sudo chmod 700 /usr/local/bin/rkhunter_scan_tg.sh
sudo chown root:root /usr/local/bin/rkhunter_scan_tg.sh
if [ "${ENABLE_RKHUNTER_SCHEDULE}" = "true" ]; then
sudo tee /etc/systemd/system/rkhunter-scan.service >/dev/null <<'EOF'
[Unit]
Description=RKHunter scan (TG notify)
After=network.target
[Service]
Type=oneshot
ExecStart=/bin/bash /usr/local/bin/rkhunter_scan_tg.sh
User=root
EOF
sudo tee /etc/systemd/system/rkhunter-scan.timer >/dev/null <<EOF
[Unit]
Description=Run RKHunter scan daily
[Timer]
OnCalendar=*-*-* ${RKHUNTER_RUN_HOUR}:${RKHUNTER_RUN_MIN}:00
Persistent=true
[Install]
WantedBy=timers.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now rkhunter-scan.timer
fi
# ==============================================================================
# 模組 4: Fail2Ban 防暴力破解 (Fail2Ban Setup)
# ==============================================================================
echo "[4/10] 設定 Fail2Ban 與 TG 阻擋通知..."
sudo tee /etc/fail2ban/action.d/telegram.conf >/dev/null <<'EOF'
[Definition]
actionban = /usr/local/bin/tg_send.sh "【Fail2Ban 防火牆阻擋】\n惡意來源 IP <ip> 嘗試登入 SSH 失敗次數過多,已被系統封鎖!"
EOF
sudo tee /etc/fail2ban/jail.d/99-tg-sshd.local >/dev/null <<EOF
[sshd]
enabled = true
bantime = 10m
findtime = 10m
maxretry = 5
action = %(action_)s
telegram
port = ${SSH_PORT}
EOF
sudo systemctl restart fail2ban || sudo fail2ban-client reload || true
# ==============================================================================
# 模組 5: USB 實體防護與異動通知 (USBGuard & Udev)
# ==============================================================================
echo "[5/10] 設定 USBGuard 實體防護與熱插拔通知..."
if [ ! -s /etc/usbguard/rules.conf ]; then
sudo sh -c 'usbguard generate-policy > /etc/usbguard/rules.conf' 2>/dev/null || true
fi
sudo tee /usr/local/bin/usb_tg_notify.sh >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
ACTION=$1; DEV_ID=$2; MODEL=$3; SERIAL=$4; PRODUCT=$5
if [ "$DEV_ID" = ":" ] && [ -n "$PRODUCT" ]; then
V_ID=$(printf "%04x" "0x$(echo "$PRODUCT" | cut -d'/' -f1)" 2>/dev/null || true)
P_ID=$(printf "%04x" "0x$(echo "$PRODUCT" | cut -d'/' -f2)" 2>/dev/null || true)
if [ -n "$V_ID" ] && [ -n "$P_ID" ]; then DEV_ID="${V_ID}:${P_ID}"; fi
fi
[ "$DEV_ID" = ":" ] || [ -n "$DEV_ID" ] || DEV_ID="未知硬體 ID"
[ -n "$MODEL" ] || MODEL="一般 USB 設備 (拔出時無法讀取)"
[ -n "$SERIAL" ] || SERIAL="無序號"
MODEL=$(echo "$MODEL" | tr '_' ' ')
if [ "$ACTION" = "add" ]; then
sleep 1.5
GUARD_INFO=$(sudo usbguard list-devices | grep -i "$DEV_ID" | head -n 1 || true)
if echo "$GUARD_INFO" | grep -q "block"; then STATE="已被系統阻擋 (Block)"
elif echo "$GUARD_INFO" | grep -q "allow"; then STATE="允許存取 (Allow)"
else STATE="狀態未知"; fi
MSG="【USB 插入警報】\n設備名稱:${MODEL}\n硬體 ID:${DEV_ID}\n設備序號:${SERIAL}\n防護狀態:${STATE}"
elif [ "$ACTION" = "remove" ]; then
MSG="【USB 拔出通知】\n設備名稱:${MODEL}\n硬體 ID:${DEV_ID}\n設備序號:${SERIAL}"
else
exit 0
fi
/usr/local/bin/tg_send.sh "$MSG" || true
EOF
sudo chmod 700 /usr/local/bin/usb_tg_notify.sh
sudo chown root:root /usr/local/bin/usb_tg_notify.sh
sudo tee /etc/udev/rules.d/99-usb-tg-notify.rules >/dev/null <<'EOF'
ACTION=="add", SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", RUN+="/usr/bin/systemd-run --no-block --collect /usr/local/bin/usb_tg_notify.sh add '%E{ID_VENDOR_ID}:%E{ID_MODEL_ID}' '%E{ID_MODEL}' '%E{ID_SERIAL_SHORT}' '%E{PRODUCT}'"
ACTION=="remove", SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", RUN+="/usr/bin/systemd-run --no-block --collect /usr/local/bin/usb_tg_notify.sh remove '%E{ID_VENDOR_ID}:%E{ID_MODEL_ID}' '%E{ID_MODEL}' '%E{ID_SERIAL_SHORT}' '%E{PRODUCT}'"
EOF
sudo udevadm control --reload-rules
# ==============================================================================
# 模組 6: 程序白名單監控 (Process Whitelist Monitor)
# ==============================================================================
echo "[6/10] 建立程序白名單與自動循環監控..."
CONF_DIR="/etc/process_monitor"
STATE_DIR="$CONF_DIR/state"
sudo mkdir -p "$STATE_DIR"
WHITELIST_FILE="$CONF_DIR/whitelist.txt"
if [ ! -s "$WHITELIST_FILE" ]; then
echo "正在掃描系統,建立初始程序白名單..."
sudo ps -e -o exe= | grep -v '^$' | sort | uniq | sudo tee "$WHITELIST_FILE" >/dev/null
else
echo "發現既有白名單,已保留原有設定 ($WHITELIST_FILE)"
fi
sudo chmod 700 "$STATE_DIR"
sudo chmod 600 "$WHITELIST_FILE"
sudo chown -R root:root "$CONF_DIR"
sudo tee /usr/local/bin/process_monitor_daemon.sh >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
WHITELIST="/etc/process_monitor/whitelist.txt"
STATE_DIR="/etc/process_monitor/state"
while true; do
find "$STATE_DIR" -type f -mmin +60 -delete 2>/dev/null || true
TMP_PROCS="$(mktemp -p /run current_procs.XXXXXX)"
ps -e -o exe= | grep -v '^$' | sed 's/ (deleted)//g' | sort | uniq > "$TMP_PROCS"
sort "$WHITELIST" -o "$WHITELIST"
NEW_PROCS=$(comm -23 "$TMP_PROCS" "$WHITELIST" || true)
rm -f "$TMP_PROCS"
if [ -n "$NEW_PROCS" ]; then
UNREPORTED=""
now=$(date +%s)
while IFS= read -r proc; do
[ -z "$proc" ] && continue
hash=$(echo -n "$proc" | md5sum | awk '{print $1}')
state_file="$STATE_DIR/$hash"
count=0; pause_until=0
if [ -f "$state_file" ]; then read -r count pause_until < "$state_file" || true; fi
if [ "$now" -lt "$pause_until" ]; then continue; fi
count=$((count + 1))
if [ "$count" -eq 30 ]; then
UNREPORTED="${UNREPORTED}- ${proc} (第 30/30 次,暫停 3 分鐘)"$'\n'
pause_until=$((now + 180)); count=0
else
UNREPORTED="${UNREPORTED}- ${proc} (第 ${count}/30 次)"$'\n'
fi
echo "$count $pause_until" > "$state_file"
done <<< "$NEW_PROCS"
if [ -n "$UNREPORTED" ]; then
MSG="【未授權程序警報】\n主機:$(hostname)\n時間:$(date '+%Y-%m-%d %H:%M:%S')\n\n偵測到未經授權程序:\n${UNREPORTED}"
/usr/local/bin/tg_send.sh "$MSG" || true
fi
fi
sleep 60
done
EOF
sudo chmod 700 /usr/local/bin/process_monitor_daemon.sh
sudo chown root:root /usr/local/bin/process_monitor_daemon.sh
sudo tee /etc/systemd/system/process-monitor.service >/dev/null <<'EOF'
[Unit]
Description=Process Whitelist Monitor
After=network.target
[Service]
Type=simple
ExecStart=/bin/bash /usr/local/bin/process_monitor_daemon.sh
Restart=always
RestartSec=5
User=root
[Install]
WantedBy=multi-user.target
EOF
# ==============================================================================
# 模組 7: 服務守護者 (Service Protector)
# ==============================================================================
echo "[7/10] 啟動系統服務雙重守護機制..."
sudo tee /usr/local/bin/service_tg_alert.sh >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
EVENT=$1; TARGET=$2
if [ "$EVENT" = "stop" ]; then
[[ "$TARGET" == *.service ]] || TARGET="${TARGET}.service"
MSG="【防護服務崩潰警報】\n被觸發服務:${TARGET}\n主機:$(hostname)\n警告:該防禦服務發生異常崩潰 (Failed)!"
elif [ "$EVENT" = "modify" ]; then
MSG="【服務檔案竄改警報】\n異動檔案:${TARGET}\n主機:$(hostname)"
else
exit 0
fi
/usr/local/bin/tg_send.sh "$MSG" || true
EOF
sudo chmod 700 /usr/local/bin/service_tg_alert.sh
sudo chown root:root /usr/local/bin/service_tg_alert.sh
sudo tee /etc/systemd/system/service-protector-alert@.service >/dev/null <<'EOF'
[Unit]
Description=Service Failure Alert for %I
[Service]
Type=oneshot
ExecStart=/usr/local/bin/service_tg_alert.sh stop %I
EOF
INOTIFY_TARGETS=""
for srv in $PROTECT_SERVICES; do
if [ "${srv##*.}" != "service" ]; then srv="${srv}.service"; fi
if ! systemctl cat "$srv" >/dev/null 2>&1; then
echo "⚠️ 警告:找不到服務 $srv ,已略過守護。"
continue
fi
DROPIN_DIR="/etc/systemd/system/${srv}.d"
sudo mkdir -p "$DROPIN_DIR"
sudo bash -c "cat << EOF > \"$DROPIN_DIR/tg_alert.conf\"
[Unit]
OnFailure=service-protector-alert@%n
EOF"
SRV_PATH=$(systemctl show -p FragmentPath "$srv" 2>/dev/null | cut -d= -f2 || true)
if [ -n "$SRV_PATH" ] && [ -e "$SRV_PATH" ]; then
INOTIFY_TARGETS="$INOTIFY_TARGETS $SRV_PATH"
fi
INOTIFY_TARGETS="$INOTIFY_TARGETS $DROPIN_DIR"
done
sudo install -o root -g root -m 600 /dev/null /etc/service-protector.targets
echo "$INOTIFY_TARGETS" | sudo tee /etc/service-protector.targets >/dev/null
sudo tee /usr/local/bin/service_file_monitor.sh >/dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
TARGETS="$(cat /etc/service-protector.targets 2>/dev/null || true)"
VALID_TARGETS=""
for t in $TARGETS; do
[ -e "$t" ] && VALID_TARGETS="$VALID_TARGETS $t"
done
if [ -z "$VALID_TARGETS" ]; then
/usr/local/bin/tg_send.sh "⚠️ service-protector 無有效監控目標,將於 30 秒後重試..." || true
sleep 30
exit 0
fi
inotifywait -m --format '%w|%e|%f' -e close_write,attrib,move,create,delete $VALID_TARGETS | \
while IFS='|' read -r path action file; do
full="${path}${file}"
if [[ "$full" == /etc/systemd/system/*.service.d/tg_alert.conf ]]; then
continue
fi
/usr/local/bin/service_tg_alert.sh modify "$full" || true
done
EOF
sudo chmod 700 /usr/local/bin/service_file_monitor.sh
sudo chown root:root /usr/local/bin/service_file_monitor.sh
sudo tee /etc/systemd/system/service-protector.service >/dev/null <<'EOF'
[Unit]
Description=Service File Protector
After=network.target
[Service]
Type=simple
ExecStart=/bin/bash /usr/local/bin/service_file_monitor.sh
Restart=always
RestartSec=30
User=root
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
# ==============================================================================
# 模組 8: 系統日誌強化與底層稽核 (Logging & Auditd)
# ==============================================================================
echo "[8/10] 強化 Journald 與安裝 Auditd 規則..."
sudo mkdir -p /etc/systemd/journald.conf.d
sudo tee /etc/systemd/journald.conf.d/99-security.conf >/dev/null <<'EOF'
[Journal]
Storage=persistent
SystemMaxUse=1G
EOF
sudo systemctl restart systemd-journald
sudo tee /etc/audit/rules.d/50-security-baseline.rules >/dev/null <<'EOF'
-w /etc/passwd -p wa -k identity_changes
-w /etc/shadow -p wa -k identity_changes
-w /etc/sudoers -p wa -k identity_changes
-w /etc/sudoers.d/ -p wa -k identity_changes
-w /var/log/audit/ -p wa -k audit_log_tampering
# 記錄命令執行(execve),便於追查(系統忙碌時可能產生大量紀錄)
-a always,exit -F arch=b64 -S execve -F euid=0 -k exec_root
-a always,exit -F arch=b64 -S execve -F auid>=1000 -F auid!=4294967295 -k exec_user
-a always,exit -F arch=b32 -S execve -F euid=0 -k exec_root
-a always,exit -F arch=b32 -S execve -F auid>=1000 -F auid!=4294967295 -k exec_user
EOF
if [ -f /var/log/auth.log ]; then
echo "-w /var/log/auth.log -p wa -k auth_log_tampering" | sudo tee -a /etc/audit/rules.d/50-security-baseline.rules >/dev/null
fi
sudo systemctl enable --now auditd
sudo augenrules --load >/dev/null 2>&1 || true
# ==============================================================================
# 最終步驟: 啟動所有背景服務 + 上線通知
# ==============================================================================
echo "[10/10] 啟動所有防護服務..."
sudo systemctl daemon-reload
sudo systemctl enable --now tg-account-monitor.service
sudo systemctl enable --now fail2ban
sudo systemctl enable --now usbguard
sudo systemctl enable --now service-protector.service
sudo systemctl enable --now process-monitor.service
FINAL_MSG="【安全系統全面上線】\n主機:$(hostname)\n時間:$(date '+%Y-%m-%d %H:%M:%S')\n-------------------------\n已啟用:\n- Token 金庫隔離 + TG 集中發送\n- 帳號/關鍵檔案監控\n- SSH 登入通知\n- SSH 指令阻擋 (ForceCommand)\n- SSH 四層強化(safe=${SSH_HARDEN_MODE})\n- UFW(${UFW_ENABLE};來源 ${UFW_ALLOW_SOURCES} → SSH:${UFW_SSH_PORT})\n- RKHunter(每日 ${RKHUNTER_RUN_HOUR}:${RKHUNTER_RUN_MIN})\n- Fail2Ban\n- USBGuard\n- Service Protector\n- Process Monitor\n- Journald + Auditd"
tg_safe_send "$FINAL_MSG"
echo "================================================================"
echo "系統全方位防護安裝完畢!您的手機應已收到上線通知。"
echo ""
echo "若需 SSH 防護例外(ForceCommand 不套用),請將使用者加入 ${SSH_RESCUE_GROUP} 群組:"
echo " sudo usermod -aG ${SSH_RESCUE_GROUP} <username>"
echo ""
if [ "${UFW_ENABLE}" = "safe" ] && is_ssh_session && ! ufw_is_active; then
echo "注意:偵測到 SSH 遠端執行,UFW 規則已寫入但尚未啟用。"
echo "確認可從 ${UFW_ALLOW_SOURCES} 連線後再手動:"
echo " sudo ufw enable"
fi
echo "================================================================"
日常維運與事件回應
系統上線後,我們進入了正式的維運階段。這套系統採用了許多嚴格的「預設拒絕」原則,因此在日常維運時,你可能會需要處理以下幾種常見的事件回應。
1. SSH 鎖死防護與救援群組管理
情境:你需要執行高權限或會被
ForceCommand黑名單阻擋的系統維護指令(例如重開機reboot),或是你需要使用密碼登入緊急處理狀況。回應方式:
系統預設保留了一個
ssh-rescue群組。此群組內的帳號不受 ForceCommand 限制,且在SSH_RESCUE_ALLOW_PASSWORD="true"時允許密碼登入。請將你需要作為「緊急逃生門」的管理員帳號加入該群組:
sudo usermod -aG ssh-rescue <你的管理員帳號>加入後,重新登入 SSH 即可獲得完整權限。
2. UFW 安全模式啟用
情境:在部署腳本時,若系統偵測到你是透過遠端 SSH 執行,且 UFW 尚未啟動,為了避免錯誤的設定導致你的連線中斷,UFW 將進入
safe模式(僅寫入規則不啟動)。回應方式:
請先確認您當前的來源 IP 確實包含在允許的網段內。確認無誤後,請手動啟用防火牆:
sudo ufw enable
3. 授權合法的新服務
情境:你剛透過
apt install或docker run部署了一套新的應用服務,隨後立刻收到了 Telegram 的「未授權行程執行警報」。回應方式:
這是預期內的行為。行程白名單在部署當下即建立了基準線。只要你確認警報中的絕對路徑是合法的新增程式,請將其路徑附加至白名單檔案中:
echo "/usr/bin/dockerd" | sudo tee -a /etc/process_monitor/whitelist.txt系統會在其後的輪詢週期中自動認可該程式,停止警報。
4. 實體裝置放行管理
情境:你需要將一個新的外接硬碟插入伺服器進行資料備份,但插入後收到「已被系統阻擋」的警報,且系統無法掛載該磁碟。
回應方式:
基於實體安全,USBGuard 預設拒絕所有未知裝置。你需要查詢該裝置的臨時 ID 並手動核發許可。
列出目前被阻擋的裝置(尋找標示為
block的項目):sudo usbguard list-devices記下該裝置最前方的數字 ID,並將其永久加入白名單:
sudo usbguard allow-device 14 -p
5. 基準線更新與誤判排除
情境:RKHunter 透過 Systemd Timer 排程掃描後,回報
/dev/shm記憶體掛載點底下存在可疑檔案(通常是 PulseAudio 或是某些共用記憶體的合法行程所產生)。回應方式:
這是防毒軟體常見的誤判/誤報。你需要對 RKHunter 進行調校並更新系統指紋基準線:
編輯設定檔
sudo nano /etc/rkhunter.conf。尋找並加入允許的特定路徑,例如:
ALLOWDEVFILE=/dev/shm/pulse-shm-*。儲存後,強制 RKHunter 重新採集並信任當前的系統狀態:
sudo rkhunter --propupd
結語
安全不是單一的產品,而是一個持續的過程。透過理解作業系統的底層運作機制,我們能夠用合理的資源損耗,編織出覆蓋面廣泛的防禦網。希望這份文件能為你的基礎架構維運帶來啟發與實質的安全提升。